#!/usr/bin/env node

const { createServer } = require('http');
const createError = require('http-errors');
const express = require('express');
const { join } = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const { install } = require('./apis');
const { error: errorHandler } = require('./resultHandler');
const { networkInterfaces } = require('os');

// 获取接口
const ips = Object.values(networkInterfaces()).reduce((t, c) => {
  t = t.concat(c)
  return t;
}, []).map(({ address }) => address).filter(_ => _.match(/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/)).filter(_ => !['127.0.0.1'].includes(_));

const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// spa 应用
app.use(express.static(join(__dirname, 'views')));
app.get(`/views/*`, (request, response) => {
  response.sendFile(join(__dirname, './views/index.html'));
});
app.all('*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "*");
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  res.header("X-Powered-By", ' 3.2.1')
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

install(app);

app.use(function (req, res, next) {
  next(createError(404));
});

app.use(function (err, req, res, next) {
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  res.status(err.status || 500);
  res.send(errorHandler({ message: err.toString() }))
  
});
const port = normalizePort(process.env.PORT || '3000');

function normalizePort(val) {
  const port = parseInt(val, 10);
  if (isNaN(port)) {
    return val;
  }
  if (port >= 0) {
    return port;
  }
  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  const bind = typeof port === 'string' ? `Pipe ${port}` : `Port ${port}`;

  switch (error.code) {
    case 'EACCES':
      console.error(`${bind} requires elevated privileges`);
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(`${bind} is already in use`);
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening() {
  console.log(`
=======================================

The process.env.NODE_ENV = ${process.env.NODE_ENV}

The application is started in

${ips.map(ip => `http://${ip}:${port}`).join('\r\n')}

use [ctrl+c] exit the application

=======================================
`);
}

// 使用环境变量配置参数，方便和各种进程工具配合
app.set('port', port);
const server = createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);